﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using GDoc.Web.Models;
using GDoc.Domain;
using GDoc.Utils;
using System.IO;
using GDoc.Domain.Services;
using GDoc.Data;

namespace GDoc.Web.Controllers
{
    [Authorize]
    public class AccountController : _ControllerBase
    {
        [HttpGet]
        public ActionResult Index(long? id)
        {
            if (id == null)
                return RedirectToAction("Index", "Home");

            AccountService accountService = new AccountService();

            Account account = accountService.GetById(id.Value);

            if (account == null)
                return RedirectToAction("Index", "Home");

            CookiesUtil.Current[Constants.Cookie_CurrentAccount] = account.Id.ToString();

            AccountIndexModel model = new AccountIndexModel
            {
                Account = account
            };

            return View(model);
        }

        [HttpGet]
        public ActionResult Select()
        {
            AccountSelectModel model = new AccountSelectModel
            {
                User = base.GetCurrentUser()
            };

            return View(model);
        }

        [HttpGet]
        public ActionResult Create()
        {
            var model = new AccountCreateModel();

            return View(model);
        }

        [HttpPost]
        public ActionResult Create(AccountCreateModel model)
        {
            if (!ModelState.IsValid)
                return View(model);

            var accountService = new AccountService();

            var account = accountService.CreateAccount(model.Name, GetCurrentUser());

            return RedirectToAction("Index", "Account", new { id = account.Id });
        }

        [HttpGet]
        public ActionResult Users()
        {
            Account account = GetCurrentAccount();

            if (account == null)
                return RedirectToAction("Index", "Home");

            AccountUsersModel model = new AccountUsersModel
            {
                Account = account
            };

            return View(model);
        }

        [HttpPost]
        public ActionResult AddGroup(string name)
        {
            Account account = GetCurrentAccount();

            if (account == null)
                return new HttpStatusCodeResult(404, "account not found");

            var group = new UserGroup { Name = name, Account = account };

            if (account.Groups.Any(g => g.Name == name))
            {
                return new HttpStatusCodeResult(409, "Ya existe un grupo con el nombre " + name + ".");
            }

            account.Groups.Add(group);

            RepositoryFactory.CreateAccountRepository().SaveOrUpdate(account);

            return Json(new
            {
                Id = group.Id,
                Name = group.Name,
                Ref = Url.Action("Group", "Account", new { id = group.Id })
            });
        }

        [HttpPost]
        public ActionResult RemoveGroup(long id)
        {
            Account account = GetCurrentAccount();

            if (account == null)
                return new HttpStatusCodeResult(404, "account not found");

            var group = account.Groups.Where(g => g.Id == id).FirstOrDefault();

            foreach (var user in group.Users.ToList())
            {
                group.Users.Remove(user);
            }

            account.Groups.Remove(group);

            RepositoryFactory.CreateAccountRepository().SaveOrUpdate(account);

            RepositoryFactory.CreateUserGroupRepository().Remove(group);

            return Json(new
            {
                Id = group.Id
            });
        }

        [HttpGet]
        public ActionResult Group(long id)
        {
            Account account = GetCurrentAccount();

            if (account == null)
                return RedirectToAction("Index", "Home");

            var group = account.Groups.Where(g => g.Id == id).FirstOrDefault();

            if (group == null)
                return new HttpStatusCodeResult(404, "group not found");

            AccountGroupModel model = new AccountGroupModel
            {
                Account = account,
                Group = group
            };

            return View(model);
        }

        [HttpGet]
        public ActionResult User(long id)
        {
            Account account = GetCurrentAccount();

            if (account == null)
                return RedirectToAction("Index", "Home");

            var user = account.Users.Where(u => u.Id == id).FirstOrDefault();

            if (user == null)
                return new HttpStatusCodeResult(404, "user not found");

            AccountUserModel model = new AccountUserModel
            {
                Account = account,
                User = user
            };

            return View(model);
        }

        [HttpPost]
        public ActionResult RemoveUserFromGroup(long uid, long gid)
        {
            Account account = GetCurrentAccount();

            if (account == null)
                return new HttpStatusCodeResult(404, "account not found");

            var group = account.Groups.Where(g => g.Id == gid).FirstOrDefault();

            if (group == null)
                return new HttpStatusCodeResult(404, "group not found");

            var user = group.Users.Where(u => u.Id == uid).FirstOrDefault();

            if (user != null)
                group.Users.Remove(user);

            RepositoryFactory.CreateUserGroupRepository().SaveOrUpdate(group);

            return Json(new
            {
                Id = group.Id
            });
        }

        [HttpPost]
        public ActionResult GetUsersForGroup(long id)
        {
            Account account = GetCurrentAccount();

            if (account == null)
                return new HttpStatusCodeResult(404, "account not found");

            var group = account.Groups.Where(g => g.Id == id).FirstOrDefault();

            if (group == null)
                return new HttpStatusCodeResult(404, "group not found");

            return Json(account.Users.Select(u => u.User).Except(group.Users).Select(u => new { Id = u.Id, Name = u.Email }));
        }

        [HttpPost]
        public ActionResult AddUsersToGroup(long id, string uids)
        {
            Account account = GetCurrentAccount();

            if (account == null)
                return new HttpStatusCodeResult(404, "account not found");

            var group = account.Groups.Where(g => g.Id == id).FirstOrDefault();

            if (group == null)
                return new HttpStatusCodeResult(404, "group not found");

            var ids = uids.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => Convert.ToInt64(v)).ToList();

            var addedUsers = new List<User>();

            ids.ForEach(uid =>
            {
                var user = account.Users.Where(u => u.User.Id == uid).Select(u => u.User).FirstOrDefault();
                if (user != null)
                {
                    addedUsers.Add(user);
                    group.Users.Add(user);
                }
            });

            RepositoryFactory.CreateUserGroupRepository().SaveOrUpdate(group);

            return Json(addedUsers.Select(u => new { Id = u.Id, Name = u.Email, Ref = Url.Action("User", "Account", new { id = u.Id }) }));
        }
    }
}
